Skip to content

fix(dialog): auto-dismiss alerts reliably and fail fast on dialog-blocked reads - #2528

Open
sx4im wants to merge 3 commits into
vercel-labs:mainfrom
sx4im:fix-2511-windows-alert-wedges-tab
Open

sx4im wants to merge 3 commits into
vercel-labs:mainfrom
sx4im:fix-2511-windows-alert-wedges-tab

Conversation

@sx4im

@sx4im sx4im commented Nov 10, 2026

Copy link
Copy Markdown

Fixes #2511

On Windows, calling alert() under the default auto-dialog handling wedged the tab: the auto-dismiss task read dialog-opening events from the shared broadcast receiver, which can lag and drop the opening event. A dropped event meant the dialog was never dismissed, so the triggering command and every later command timed out after about 30 seconds with os error 10060 until close reported page_wedged.

What changed:

  • The dialog handler now listens for Page.javascriptDialogOpening on a lossless method tap instead of the shared broadcast, so the opening event cannot be dropped.
  • Every dialog is tracked in pending_dialog, including ones the background task auto-dismisses, so dialog status and the fail-fast gate see an open alert instead of a wedged tab.
  • url and title now fail fast while a dialog is open, since both evaluate JavaScript in the page and hung until the client read timeout.

How verified:

  • cargo fmt --check passes.
  • Two new e2e tests cover the alert auto-dismiss and the fail-fast title read, plus a rewritten unit test for the dialog drain.
  • The Windows repro could not run locally and the full cargo test binary did not finish building here (out of memory), so CI is the real verification for this one.

…cked reads

On Windows, alert() under the default auto-dialog handling wedged the tab:
the auto-dismiss task read dialog-opening events from the shared broadcast
receiver, which can lag and drop the opening event. A dropped event meant
the dialog was never dismissed, so the triggering command and every later
command timed out after ~30 s with os error 10060 until close reported
page_wedged. `dialog status` also reported no dialog, since auto-handled
dialogs were never tracked.

Listen for Page.javascriptDialogOpening on a lossless method tap instead of
the shared broadcast, and track every dialog in pending_dialog, including
the ones the background task auto-dismisses. The dismiss usually lands
first and the closed event clears the tracking on the next drain; but if
the dismiss is missed or fails, the dialog stays visible to `dialog
status`, the fail-fast gate, and the timeout path, so an open alert no
longer looks like a wedged tab.

Also fail fast for `url` and `title` while a dialog is open: both evaluate
JavaScript in the page, so they hung until the client read timeout instead
of reporting the blocking dialog. `dialog`, `screenshot`, and tab
management stay usable during a dialog.

Fixes vercel-labs#2511
@vercel

vercel Bot commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

@sx4im is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@vercel vercel Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional findings

  1. cli/src/native/actions.rs:2264-2283 — If broadcast lag drops an auto-dismissed alert's close event after its opening was drained, the new tracking leaves page commands blocked by a dialog that no longer exists.

    Fix on Vercel

Comment thread cli/src/native/actions.rs Resolved
Vercel review on vercel-labs#2528 found two issues in the dialog tracking:

1. If broadcast lag dropped an auto-dismissed alert's close event after
its opening was drained, pending_dialog stayed set forever and page
commands kept failing fast on a dialog that no longer exists. The
background task saw the same opening on its lossless tap and already
dismissed it, so on lag the tracked alert/beforeunload entry is stale:
clear it. Confirm/prompt dialogs are never auto-dismissed, so their
entries stay tracked.

2. The dialog-drain unit test always panicked: the drain's session filter
discarded dialog events with no browser attached. Dialog open/close is
daemon-global state, so dialog events bypass the session filter (the
fail-fast gate still scopes to the active tab), and a close only clears
the dialog it closed.
Comment thread cli/src/native/actions.rs Resolved
@vercel-internal-security-reviewer

Copy link
Copy Markdown

Security review details

Vercel review on vercel-labs#2528 (comment 4523632585): tracking a background-tab
dialog without updating dialog resolution made `dialog accept` and
`dialog dismiss` target the active tab instead of the reported dialog.
BrowserManager::handle_dialog always used the active session. It now
takes the tracked dialog's session (falling back to the active session
when none is recorded, e.g. a top-level page dialog), and the CLI
`dialog` handler passes pending_dialog's session_id. The fail-fast gate
already scoped blocking to the active tab; only the resolution path was
still active-tab bound.

New mock-CDP unit test pins both halves: a background-tab dialog is
answered on its own session, and a missing session falls back to the
active tab.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows: alert() wedges the tab under default auto-dialog handling (os error 10060, page_wedged); --no-auto-dialog + dialog accept works

1 participant